import { observable, action, computed, runInAction, toJS } from 'mobx';

import BaseStore from '../BaseStore';
import validationUtil from '@/utils/validation';
import { noticeMessage } from '@utils/common-message';

class Store extends BaseStore {

    @observable editRoleId;
    @observable editRoleName;
    @observable editRoleDescription;
    @observable templateTree;
    @observable _checkedTreeNodes;
    @observable _treeChildrenMap;
    defaultMenus;

    @observable errMsg = {
        editRoleName: '',
        editRoleDescription: '',
    };

    isEditSuccess;
    globalErrMsg;

    @computed
    get templateTreeData() {
        return toJS(this.templateTree);
    }

    @computed
    get checkedTreeNodes() {
        return toJS(this._checkedTreeNodes);
    }

    @computed
    get treeChildrenMap() {
        return toJS(this._treeChildrenMap);
    }


    @computed
    get isEditSubmitBtnDisabled() {
        return !this.editRoleName ||
            !this.editRoleName.trim() ||
            !this.checkedTreeNodes ||
            !this.checkedTreeNodes.checked || 
            this.checkedTreeNodes.checked.length < 1;
    }

    @action
    reset() {
        this.templateTree = null;
        this.editRoleId = null;
        this.editRoleName = null;
        this.editRoleDescription = null;
        this._checkedTreeNodes = null;
        this._treeChildrenMap = null;
        this.defaultMenus = null;
        this.isEditSuccess = false;
        this.errMsg = {
            editRoleName: '',
            editRoleDescription: '',
        };
    }

    @action
    init(daa) {
        this.fetchTemplateTree();
        if (this.editRoleId) {
            this.fetchRoleDetail();
        }
    }

    @action
    setCheckedTreeNodes() {
        const tree = this.templateTreeData;
        const defaultMenus = this.defaultMenus;
        if (!tree || tree.length === 0 || !defaultMenus || defaultMenus.length === 0) {
            return;
        }
        // const {menus, modules} = getLastChildrenKeys(defaultMenus);
        const { menus, modules } = getAllKeys(defaultMenus);
        const checkedTreeNodes = [
            ...menus,
            ...modules
        ];
        this.refreshTreeCheckedNodes(checkedTreeNodes);
    }

    @action
    updateTreeCheckedNodes(currentNodeKey) {
        const treeChildrenMap = this.treeChildrenMap;
        if (!treeChildrenMap) {
            return;
        }
        let checkedTreeNodes = this.checkedTreeNodes || {};
        let checkedNodes = checkedTreeNodes.checked || [];
        let halfCheckedNodes = checkedTreeNodes.halfChecked || [];
        const childrenMap = treeChildrenMap[currentNodeKey];
        if (checkedNodes.indexOf(currentNodeKey) !== -1) {
            // 从选中状态变为非选中状态，需要将该节点及其所有子节点标记为未选中状态
            let willCancelCheckedNodes = [currentNodeKey];
            if (childrenMap && childrenMap.children) {
                willCancelCheckedNodes = willCancelCheckedNodes.concat(childrenMap.children);
            }
            checkedNodes = checkedNodes.filter(item => willCancelCheckedNodes.indexOf(item) === -1);
        } else {
            // 从半选状态或者未选中状态变成选中状态，需要将该节点及其所有子节点标记为选中状态
            let willCheckedNodes = [currentNodeKey];
            if (childrenMap && childrenMap.children) {
                willCheckedNodes = willCheckedNodes.concat(childrenMap.children);
            }
            checkedNodes = checkedNodes.concat(willCheckedNodes);
        }
        this.refreshTreeCheckedNodes(Array.from(new Set(checkedNodes.concat(halfCheckedNodes))));
    }

    @action
    refreshTreeCheckedNodes(partOfCheckedNodes) {
        let checkedNodes = [];
        let halfCheckedNodes = [];
        const treeChildrenMap = this.treeChildrenMap || {};
        for (let nodeKey in treeChildrenMap) {
            const { children, lastLevelChildren } = treeChildrenMap[nodeKey];
            const checkedLastLevelChildren = partOfCheckedNodes.filter(item => lastLevelChildren.indexOf(item) !== -1);
            if (checkedLastLevelChildren.length < 1) {
                // 没有子项被选中
                if (partOfCheckedNodes.indexOf(nodeKey) !== -1) {
                    // 子项未选中，但是自己选中时标记为半选状态
                    halfCheckedNodes.push(nodeKey);
                }
            } else if (checkedLastLevelChildren.length === lastLevelChildren.length) {
                // 所有子项选中
                checkedNodes = Array.from(new Set([
                    ...checkedNodes,
                    ...children,
                    nodeKey,
                ]));
            } else {
                // 有部分子项选中
                halfCheckedNodes.push(nodeKey);
                checkedNodes = [
                    ...checkedNodes,
                    ...checkedLastLevelChildren,
                ];
            }
        }
        this._checkedTreeNodes = {
            checked: checkedNodes,
            halfChecked: halfCheckedNodes,
        };
    }

    @action
    async fetchRoleDetail() {
        const res = await this.get(`/auth/roles/${this.editRoleId}/detail`, null, {
            showGlobalLoading: true,
        });
        runInAction(() => {
            if (res.code === '0000') {
                const data = res.data;
                this.editRoleName = data.name;
                this.editRoleDescription = data.description;
                this.defaultMenus = data.menus;
                this.setCheckedTreeNodes();
            }
        });
    }

    @action
    async fetchTemplateTree() {
        const res = await this.get('/auth/templete-tree', null, {
            showGlobalLoading: true,
        });
        runInAction(() => {
            if (res.code === '0000') {
                this.templateTree = res.data;
                let treeChildrenMap = {};
                createTreeChildrenMap(res.data, treeChildrenMap);
                this._treeChildrenMap = treeChildrenMap;
            } else {
                this.templateTree = null;
            }
            this.setCheckedTreeNodes();
        });
    }

    @action
    async editSubmit() {
        this.globalErrMsg = '';
        // const { menus, modules } = this.checkedTreeNodes && getAllIdsByChildrenKeys(this.templateTreeData, [...this.checkedTreeNodesData]) || {};
        const { checked, halfChecked } = this.checkedTreeNodes;
        let menus = [];
        let modules = [];
        [...checked, ...halfChecked].forEach(item => {
            const [prefix, id] = item.split('-');
            if (prefix === 'menu') {
                menus.push(parseInt(id, 10));
            } else {
                modules.push(parseInt(id, 10));
            }
        });
        let url, data;
        data = {
            name: this.editRoleName.trim(),
            description: this.editRoleDescription && this.editRoleDescription.trim() || '',
            menus: menus || null,
            modules: modules || null,
        }
        if (this.editRoleId) {
            url = `/auth/roles/${this.editRoleId}/edit`;
        } else {
            url = '/auth/roles/add';
        }
        const res = await this.post(url, data, {
            showGlobalLoading: true,
        });
        const code = res.code;
        runInAction(() => {
            if (code === '0000') {
                this.isEditSuccess = true;
            } else if (code === '1201') {
                this.globalErrMsg = '无此操作权限，请重试或联系管理员';
            } else if (code === '1202') {
                this.errMsg.editRoleName = '角色名称已存在，请重新填写角色名称';
            } else {
                this.globalErrMsg = `${this.editRoleId ? '编辑' : '新增'}角色失败，请重试`;
            }
        });
    }
}

// 根据提供的moji
function getAllIdsByChildrenKeys(data, keys) {
    if (!data || !keys || data.length < 1 || keys.length < 1) {
        return null;
    }

    let result = {
        menus: [],
        modules: []
    };
    for (let i = 0, len = data.length; i < len; i++) {
        const item = data[i];
        let idxMenu, idxModule;
        if (item.menus && item.menus.length) {
            const { menus, modules } = getAllIdsByChildrenKeys(item.menus, keys);
            if (menus.length || modules.length) {
                menus.push(item.id);
                result.menus = result.menus.concat(menus);
                result.modules = result.modules.concat(modules);
            }
            idxMenu = keys.indexOf('menu-' + item.id);
            if (idxMenu !== -1) {
                keys.splice(idxMenu, 1);
            }
        } else if (item.modules && item.modules.length) {
            const { modules } = getAllIdsByChildrenKeys(item.modules, keys);
            if (modules.length) {
                result.menus.push(item.id);
                result.modules = result.modules.concat(modules);
            }
            idxMenu = keys.indexOf('menu-' + item.id);
            if (idxMenu !== -1) {
                keys.splice(idxMenu, 1);
            }
        } else {
            if ('modules' in item) {
                // 该层级是菜单
                idxMenu = keys.indexOf('menu-' + item.id);
                if (idxMenu !== -1) {
                    result.menus.push(item.id);
                }
            } else {
                // 该层级是
                idxModule = keys.indexOf('module-' + item.id);
                if (idxModule !== -1) {
                    result.modules.push(item.id);
                }
            }
        }
        if (keys.length === 0) {
            return result;
        }
    }
    return result;
}

function getLastChildrenKeys(data) {
    let menus = [];
    let modules = [];
    data && data.length && data.forEach(item => {
        if (!item.menus || !item.menus.length) {
            if (item.modules && item.modules.length) {
                item.modules.forEach(itm => modules.push(`module-${itm.id}`));
            } else {
                menus.push(`menu-${item.id}`);
            }
        } else {
            const result = getLastChildrenKeys(item.menus);
            menus = menus.concat(result.menus);
            modules = modules.concat(result.modules);
        }
    });
    return {
        menus,
        modules
    }
}

function getAllKeys(data) {
    let menus = [];
    let modules = [];
    data && data.length && data.forEach(item => {
        menus.push(`menu-${item.id}`);
        if (!item.menus || !item.menus.length) {
            if (item.modules && item.modules.length) {
                item.modules.forEach(itm => modules.push(`module-${itm.id}`));
            }
        } else {
            const result = getAllKeys(item.menus);
            menus = menus.concat(result.menus);
            modules = modules.concat(result.modules);
        }
    });
    return {
        menus,
        modules
    }
}

function createTreeChildrenMap(tree, treeChildrenMap) {
    let children = [];
    let lastLevelChildren = [];
    tree && tree.forEach(item => {
        const id = `${'modules' in item ? 'menu' : 'module'}-${item.id}`;
        const { menus, modules } = item;
        children.push(id);
        if (menus && menus.length > 0 || modules && modules.length) {
            const treeChildrenData = createTreeChildrenMap(menus && menus.length > 0 ? menus : modules, treeChildrenMap);
            treeChildrenMap[id] = treeChildrenData;
            children = children.concat(treeChildrenData.children);
            lastLevelChildren = lastLevelChildren.concat(treeChildrenData.lastLevelChildren);
        } else {
            // 末级节点
            lastLevelChildren.push(id);
        }
    });
    return {
        children,
        lastLevelChildren,
    }
}

export default new Store();
